package com.baiye.www.protocol;

import com.baiye.www.config.Config;
import com.baiye.www.message.Message;
import com.baiye.www.serializer.SerializeType;
import com.baiye.www.serializer.Serializer;
import com.google.common.primitives.Longs;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageCodec;
import io.netty.handler.codec.MessageToMessageCodec;

import java.util.List;

/**
 * @author baiye
 * @version 1.0
 * @date 2021/12/2 10:37
 */
@ChannelHandler.Sharable
public class MessageCodec extends MessageToMessageCodec<ByteBuf, Message>        {
    @Override
    protected void encode(ChannelHandlerContext channelHandlerContext, Message message, List<Object> outList) throws Exception {
        ByteBuf out = channelHandlerContext.alloc().buffer();
        //魔数 5字节
        out.writeBytes(new byte[]{'b','a','i','y','e'});
        //版本号 1字节
        out.writeByte(1);
        //序列化方式 1字节
        out.writeByte(Config.SERIALIZER.ordinal());
        //消息类型 1字节
        out.writeByte(message.getMessageType());
        // 消息序列号 8字节
        out.writeBytes(Longs.toByteArray(message.getSequenceId()));
        //序列化后的消息内容
        byte[] bytes = new byte[0];
        try {
            bytes = Config.SERIALIZER.serialize(message);
        } catch (Exception e) {
            e.printStackTrace();
        }
        //消息长度
        out.writeInt(bytes.length);
        //写入消息内容
        out.writeBytes(bytes);
        outList.add(out);
    }

    @Override
    protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List<Object> list) throws Exception {
        byte[] magic=new byte[5];
        //魔数 5字节
        byteBuf.readBytes(magic,0,magic.length);
        //版本号 1字节
        byte version=byteBuf.readByte();
        //序列化方式 1字节
        byte serializationType = byteBuf.readByte();
        //消息类型 1字节
        byte messageType=byteBuf.readByte();
        //消息序列号 8字节
        long sequenceId=byteBuf.readLong();
        //消息长度
        int length=byteBuf.readInt();
        //消息具体内容
        byte[] bytes = new byte[length];
        byteBuf.readBytes(bytes, 0, length);
        //反序列化后的消息内容
        SerializeType type = SerializeType.values()[serializationType];
        Class<? extends Message> messageClass = Message.getMessageClass(messageType);
        Message message = null;
        try {
            message = type.deserialize(messageClass, bytes);
        } catch (Exception e) {
            e.printStackTrace();
        }
        list.add(message);

    }
}
